package prober

import (
	"fmt"
	"os"
	"strings"
	"time"
)

// Prober 用于分析一段串行程序各处探针的耗时占比
type Prober struct {
	title        string
	times        []*time.Time
	comments     []string
	endProbeCall bool // 没有设计为线程安全，场景不需要
}

func NewProber(title string) *Prober {
	return &Prober{
		title: title,
	}
}

func (p *Prober) AddProbe(comment string) {
	now := time.Now()
	p.times = append(p.times, &now)
	p.comments = append(p.comments, comment)
}

func (p *Prober) EndProbe() {
	// EndProbe only called once for a prober
	if p.endProbeCall {
		panic("EndProbe can only be called once for a prober")
	}
	p.endProbeCall = true
	now := time.Now()
	p.times = append(p.times, &now)
}

// Report 以csv格式字符串展示耗时报告
func (p *Prober) Report() string {
	if !p.endProbeCall {
		panic("EndProbe Must be called before Report is called")
	}
	reportBuf := &strings.Builder{}
	// write table header
	reportBuf.WriteString("probe,cost-time,ratio\n")
	// write table data
	probes := make([]string, len(p.comments))
	costs := make([]time.Duration, len(p.comments))
	ratios := make([]float64, len(p.comments))
	totalCost := p.times[len(p.times)-1].Sub(*p.times[0])
	for i := 0; i < len(p.comments); i++ {
		probes[i] = p.comments[i]
		costs[i] = p.times[i+1].Sub(*p.times[i])
		ratios[i] = float64(costs[i]) / float64(totalCost) * 100
		reportBuf.WriteString(fmt.Sprintf("%v,%v,%.2f%%\n",
			probes[i],
			costs[i],
			ratios[i],
		))
	}
	reportStr := reportBuf.String()
	os.WriteFile(p.title+".csv", []byte(reportStr), os.ModePerm)
	return reportStr
}
